import React, { FC, lazy, ReactNode, Suspense } from 'react';
import { Skeleton } from '@douyinfe/semi-ui';

interface LoadableOptionsLoader <T extends Record<string, any>> {
  (): Promise<{
    default: React.FC<T>;
  }>
}

interface LoadableOptions <T extends Record<string, any> = any> {
  /** 加载器，默认不支持传参 */
  loader: LoadableOptionsLoader<T>;
  fallback?: ReactNode;
}

interface LoadableFunction {
  <T extends Record<string, any> = any> (
    options: LoadableOptions<T> | LoadableOptionsLoader<T>
  ): FC<T>;
}

const Loadable: LoadableFunction = (arg) => {
  const options = typeof arg === 'function'
    ? { loader: arg, fallback: <Skeleton /> }
    : { loader: arg.loader, fallback: arg.fallback ?? <Skeleton /> };

  const { fallback, loader } = options;
  
  return (props: any) => {
    const LoadComponent = lazy(loader);

    return (
      <Suspense fallback={options.fallback}>
        <LoadComponent {...props} />
      </Suspense>
    );
  }
}

export default Loadable;